package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tbit.uqbike.constant.ActivityConstant;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.ActivityDTO;
import com.tbit.uqbike.object.pojo.vo.ActivityVO;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.quartz.ActivityQuartz;
import com.tbit.uqbike.service.business.ActivityService;
import com.tbit.uqbike.webmanager.dao.core.ActivityDao;
import com.tbit.uqbike.webmanager.dao.core.ActivityDetailDao;
import com.tbit.uqbike.webmanager.dao.log.ActiveStatDao;
import com.tbit.uqbike.webmanager.dao.log.EvenJoinDetailDao;
import com.tbit.uqbike.webmanager.dao.log.UserRewardLogDao;
import com.tbit.uqbike.webmanager.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 活动管理接口实现类
 *
 * @Author:BUGTian
 * @DATE: 2022/5/17
 */
@Service
public class ActivityServiceImpl implements ActivityService {

    @Autowired
    private ActivityDao activityDao;

    @Autowired
    private ActivityDetailDao activityDetailDao;

    @Autowired
    private ActiveStatDao activeStatDao;

    @Autowired
    private EvenJoinDetailDao evenJoinDetailDao;

    @Autowired
    private UserRewardLogDao userRewardLogDao;

    @Autowired
    private ActivityQuartz activityQuartz;

    @Override
    //@Transactional
    public Result addActivity(ActivityDTO activityDTO) {
        //查询当前区域的生效中的活动
        check(activityDTO);
        Activity ActivityIng = activityDao.selectByType(0, activityDTO.getAccountId());
        if (ActivityIng != null) {
            return Result.error("当前类型活动已存在，不允许新增");
        }
        Activity activity = new Activity();
        activity.setInviteId(activityDTO.getId())
                .setAccountId(activityDTO.getAccountId())
                .setName(activityDTO.getName())
                .setDescription(activityDTO.getDescription())
                .setEventUrl(activityDTO.getEventUrl())
                .setStartTime(activityDTO.getStartTime())
                .setEndTime(activityDTO.getEndTime())
                .setExpireTime(activityDTO.getEndTime())
                .setValidDay(activityDTO.getValidDay())
                .setType(0)
                .setIsvalid(ActivityConstant.UN_START)
                .setState(ActivityConstant.CLOSE);
        //活动详情
        ActivityDetail activityDetail = new ActivityDetail();
        activityDetail
                .setRewardId(activityDTO.getRewardId())
                .setValidDay(activityDTO.getValidDay())
                .setGiveType(activityDTO.getGiveType())
                .setPushType(activityDTO.getPushType())
                .setFrequency(activityDTO.getFrequency())
                .setActiveObject(0).setNumber(activityDTO.getNumber());
        //添加邀请新用户要新增四个详情
        activityDao.insert(activity);
        //设置返回的主键
        activityDetail.setInviteId(activity.getInviteId());
        for (int i = 0; i < 4; i++) {
            activityDetail.setType(i);
            activityDetail.setRewardNum(getRewardNum(activityDTO, i));
            activityDetailDao.insert(activityDetail);
        }
        return Result.success();
    }

    @Override
    //@Transactional
    public Result update(ActivityDTO activityDTO) {
        //参数校验
        check(activityDTO);
        Integer id = activityDTO.getId();
        if (id == null) {
            return Result.error("参数有误");
        }
        //根据主键查询当前活动
        Activity activity = activityDao.selectById(id);
        if (activity == null) {
            return Result.error("活动不存在");
        }
        switch (activity.getIsvalid()) {
            case 0:
                //未开始,允许修改，但开始时间不能小于当前时间
                long time = DateUtil.beginOfDay(new Date()).getTime();
                if (activityDTO.getStartTime().getTime() < time) {
                    throw new BaseException("开始时间不能小于当前时间");
                }
                break;
            case 1:
                //进行中,不允许修改开始时间
                if (activity.getStartTime().getTime() != activityDTO.getStartTime().getTime()) {
                    return Result.error("活动进行中，不允许修改开始时间");
                }
                break;
            case 2:
                //已结束,不允许修改
                return Result.error("活动已结束，不允许修改");
            default:
                //不进行任何操作
                break;
        }
        activity.setEventUrl(activityDTO.getEventUrl())
                .setStartTime(activityDTO.getStartTime())
                .setEndTime(activityDTO.getEndTime())
                .setExpireTime(activityDTO.getEndTime())
                .setValidDay(activityDTO.getValidDay());
        activityDao.update(activity);
        //更新详情
        ActivityDetail activityDetail = new ActivityDetail();
        activityDetail.setInviteId(activityDTO.getId());
        BeanUtils.copyProperties(activityDTO, activityDetail);
        for (int i = 0; i < 4; i++) {
            activityDetail.setType(i);
            //根据类型赋值
            activityDetail.setRewardNum(getRewardNum(activityDTO, i));
            activityDetailDao.updateByTypeAndEventId(activityDetail);
        }
        return Result.success();
    }

    @Override
    public Result<ActivityVO> queryById(Integer id) {
        ActivityVO activityVO = new ActivityVO();
        Activity activity = activityDao.selectById(id);
        if (activity == null) {
            return Result.error("活动信息不存在");
        }
        BeanUtils.copyProperties(activity, activityVO);
        activityVO.setId(activity.getInviteId());
        //根据活动id查询详情信息
        List<ActivityDetail> activityDetailList = activityDetailDao.selectByInviteId(id);
        for (ActivityDetail activityDetail : activityDetailList) {
            Integer rewardNum = activityDetail.getRewardNum();
            switch (activityDetail.getType()) {
                case 0:
                    //仅需赋值一次
                    activityVO.setFrequency(activityDetail.getFrequency())
                            .setNumber(activityDetail.getNumber())
                            .setGiveType(activityDetail.getGiveType())
                            .setRewardId(activityDetail.getRewardId())
                            .setPushType(activityDetail.getPushType());
                    activityVO.setAcceptShareCount(rewardNum);
                    break;
                case 1:
                    activityVO.setAcceptFirstRideCount(rewardNum);
                    break;
                case 2:
                    activityVO.setInitiateShareCount(rewardNum);
                    break;
                case 3:
                    activityVO.setInitiateFirstRideCount(rewardNum);
                    break;
                default:
                    break;
            }
        }
        return Result.success(activityVO);
    }

    @Override
    public PageResult<Activity> queryPage(Integer page, Integer size, Integer accountId, Integer isvalid) {
        PageInfo<Activity> pageInfo = PageHelper.startPage(page, size).doSelectPageInfo(() -> activityDao.selectList(accountId, isvalid));
        return new PageResult<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public Result activitySwitch(Integer id) {
        Activity activity = activityDao.selectById(id);
        if (activity == null) {
            throw new BaseException("活动不存在");
        }
        Integer isvalid = activity.getIsvalid();
        if (ActivityConstant.END.equals(isvalid)) {
            //已结束的活动不允许修改
            return Result.error("已结束的活动不允许开启");
        }
        if (ActivityConstant.OPEN.equals(activity.getState())) {
            //活动本身是开启状态，可以关闭
            if (ActivityConstant.START.equals(isvalid)) {
                //活动进行中,关闭并修改状态为结束,实际结束时间修改为当前
                activityDao.updateState(id, ActivityConstant.END, ActivityConstant.CLOSE);
                activityDao.updateExpireTime(id, new Date());
            }
            if (ActivityConstant.UN_START.equals(isvalid)) {
                //活动未开始，直接关闭
                activityDao.updateState(id, isvalid, ActivityConstant.CLOSE);
            }
        } else {
            //活动本身是关闭状态,查询当前区域是否已有开启的活动
            int count = activityDao.queryOpenCountByAccountId(activity.getAccountId(), ActivityConstant.OPEN);
            if (count > 0) {
                return Result.error("开启失败,当前区域已有开启的活动");
            }
            activityDao.updateState(id, isvalid, ActivityConstant.OPEN);
        }
        //更新活动状态
        activityQuartz.updateActivityStateQuartz();
        return Result.success();
    }

    @Override
    public Result<List<ActiveStat>> activeStatCount(Integer accountId, Integer adAccountId, String startTime, String endTime, Integer eventType) {
        List<ActiveStat> activeStats = activeStatDao.activeStatCount(accountId, adAccountId, startTime, endTime, eventType);
        Map<String, ActiveStat> activeStatMap = new HashMap<>();
        activeStats.forEach(activeStat -> activeStatMap.put(activeStat.getDate(), activeStat));
        //获取时间区间的每一天,进行补全
        DateTime parseStartTime = DateUtil.parse(startTime);
        long betweenDay = DateUtil.between(parseStartTime, DateUtil.parse(endTime), DateUnit.DAY);
        activeStats.clear();
        for (long i = 0; i < betweenDay + 1; i++) {
            String date = DateUtil.formatDate(DateUtil.offsetDay(parseStartTime, (int) i));
            ActiveStat activeStat = activeStatMap.get(date);
            if (activeStat == null) {
                //数据库没有这天的数据，需要补全
                activeStats.add(new ActiveStat().setDate(date));
            } else {
                activeStats.add(activeStat);
            }
        }

        return Result.success(activeStats);
    }

    @Override
    public Result<PageResult<ActiveStat>> activeStatCountPage(Integer accountId, Integer adAccountId, String startTime, String endTime, Integer eventType, Integer page, Integer size) {
        PageInfo<ActiveStat> pageInfo = PageHelper.startPage(page, size).doSelectPageInfo(() -> activeStatDao.activeStatCount(accountId, adAccountId, startTime, endTime, eventType));
        return Result.success(new PageResult<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList()));
    }

    @Override
    public List<EvenJoinDetail> activeCountNumber(Integer accountId, Integer adAccountId, Integer eventType) {
        //根据活动类型统计人数
        List<EvenJoinDetail> evenJoinDetails = evenJoinDetailDao.activeCountNumber(accountId, adAccountId, eventType);
        Map<Integer, EvenJoinDetail> map = new HashMap<>();
        if (evenJoinDetails != null && evenJoinDetails.size() > 0) {
            evenJoinDetails.forEach(evenJoinDetail -> map.put(evenJoinDetail.getType(), evenJoinDetail));
        }
        assert evenJoinDetails != null;
        evenJoinDetails.clear();
        for (int i = 0; i < 4; i++) {
            EvenJoinDetail evenJoinDetail = map.get(i);
            evenJoinDetails.add(evenJoinDetail == null ? new EvenJoinDetail()
                    .setType(i).setUserCount(0).setMan(0).setWoman(0).setJuvenile(0).setTeenager(0).setYoungMan(0).setMiddleAged(0).setElderly(0) : evenJoinDetail);
        }
        return evenJoinDetails;
    }

    @Override
    public PageResult<UserRewardLog> queryUserRewardLog(Integer page, Integer size, Integer adAccountId, Integer accountId, Date startTime, Date endTime, String invitePhone, Integer eventId, Integer eventType, String rewardName) {
        PageInfo<UserRewardLog> pageInfo = PageHelper.startPage(page, size).doSelectPageInfo(() -> userRewardLogDao.queryUserRewardLog(adAccountId, accountId, startTime, endTime, invitePhone, eventId, eventType, rewardName));
        return new PageResult<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }


    @Override
    public PageResult<UserRewardRank> queryUserRewardRank(Integer page, Integer size, Integer accountId, Integer eventId) {
        PageInfo<UserRewardRank> pageInfo = PageHelper.startPage(page, size).doSelectPageInfo(() -> userRewardLogDao.queryUserRewardRank(accountId, eventId));
        List<UserRewardRank> list = pageInfo.getList();
        int rank = (page - 1) * size;
        if (list != null && list.size() > 0) {
            for (UserRewardRank userRewardRank : list) {
                //赋值排名
                userRewardRank.setRank(++rank);
            }
        }
        return new PageResult<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), list);
    }

    @Override
    public Result deleteActivity(Integer id) {
        Activity activity = activityDao.selectById(id);
        if (activity == null) {
            return Result.error("活动不存在");
        }
        //活动状态
        Integer isvalid = activity.getIsvalid();
        if (ActivityConstant.OPEN.equals(isvalid)) {
            return Result.error("活动进行中,删除失败");
        }
        if (ActivityConstant.END.equals(isvalid)) {
            return Result.error("生效过的活动历史,不允许删除");
        }
        //删除活动信息
        activityDao.deleteById(id);
        //根据活动id删除活动详情
        activityDetailDao.deleteByInviteId(id);
        return Result.success();
    }


    /**
     * 根据详情type获取赠送的数量
     *
     * @param activityDTO
     * @param type
     * @return
     */
    public Integer getRewardNum(ActivityDTO activityDTO, Integer type) {
        switch (type) {
            case 0:
                //接受邀请接收人赠送
                return activityDTO.getAcceptShareCount();
            case 1:
                //完成接收人赠送
                return activityDTO.getAcceptFirstRideCount();
            case 2:
                //接受邀请邀请人赠送
                return activityDTO.getInitiateShareCount();
            case 3:
                //完成邀请人赠送
                return activityDTO.getInitiateFirstRideCount();
            default:
                return 0;
        }
    }

    /**
     * 参数校验
     *
     * @param activityDTO 新增和更新入参
     */
    void check(ActivityDTO activityDTO) {
        if (StringUtils.isEmpty(activityDTO.getName())) {
            throw new BaseException("活动名称不能为空");
        }
        if (StringUtils.isEmpty(activityDTO.getDescription())) {
            throw new BaseException("活动描述不能为空");
        }
        if (activityDTO.getAccountId() == null) {
            throw new BaseException("区域不能为空");
        }
        long timeMillis = System.currentTimeMillis();
        long time = DateUtil.beginOfDay(new Date()).getTime();
        Integer id = activityDTO.getId();
        //新增时，开始时间不能小于当前时间
        if (id == null && activityDTO.getStartTime().getTime() < time) {
            throw new BaseException("开始时间不能小于当前时间");
        }
        if (activityDTO.getEndTime().getTime() < timeMillis) {
            throw new BaseException("结束时间不能小于当前时间");
        }
        if (activityDTO.getEndTime().getTime() < activityDTO.getStartTime().getTime()) {
            throw new BaseException("开始时间不能小于结束时间");
        }
        //赠送数量默认给0
        if (activityDTO.getInitiateShareCount() == null) {
            activityDTO.setInitiateShareCount(0);
        }
        if (activityDTO.getAcceptShareCount() == null) {
            activityDTO.setAcceptShareCount(0);
        }
        if (activityDTO.getInitiateFirstRideCount() == null) {
            activityDTO.setInitiateFirstRideCount(0);
        }
        if (activityDTO.getAcceptFirstRideCount() == null) {
            activityDTO.setAcceptFirstRideCount(0);
        }
    }
}
